package com.syni.mdd.yhd.common.all.service.impl;

import com.alibaba.fastjson.JSON;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.dao.jpa.BmsBusinessFlowDao;
import com.syni.mdd.yhd.common.all.entity.BmsBusinessFlow;
import com.syni.mdd.yhd.common.all.entity.flow.FlowDocument;
import com.syni.mdd.yhd.common.all.listen.flow.BusinessFlowEvent;
import com.syni.mdd.yhd.common.all.service.BmsBusinessFlowService;
import com.syni.mdd.yhd.common.all.service.BmsCommonService;
import com.syni.mdd.yhd.common.all.utils.RestTemplateUtils;
import com.syni.mdd.yhd.common.all.utils.StringUtils;
import com.syni.mdd.sjb.common.component.utils.common.utils.AppConfig;
import com.syni.mdd.sjb.common.component.utils.common.utils.ParamsMap;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import lombok.extern.log4j.Log4j2;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @className
 * @description TOO
 * @Author cfx
 * @DATE 2019/4/9 12:04
 * @VERSION 1.0
 **/
@Service
@Log4j2
public class BmsBusinessFlowServiceImpl implements BmsBusinessFlowService {
    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    BmsBusinessFlowDao bmsBusinessFlowDao;

    @Autowired
    RedisTemplate redisTemplate;

    @Override
    public BmsBusinessFlowDao getBaseDao() {
        return bmsBusinessFlowDao;
    }

    @Override
    public Map<String, Object> getToken(ParamsMap paramsMap) {
        String redisKey = Constants.REDIS_KEY_FLOW_TOKEN;
        Map<String,Object> resultMap = new HashMap<>();
        if(redisTemplate.hasKey(redisKey)){
            String token = redisTemplate.opsForValue().get(redisKey).toString();
            resultMap.put("token",token);
            return ResultMapHelper.success(resultMap,ResultMsg.MSG_GET_SUCCESS);
        }
        final String getTokenUrl = "https://openapi.esign.cn/v1/oauth2/access_token";
        Map<String,Object> params = new HashMap<>();
        params.put("appId", AppConfig.getProperty(Constants.FLOW_APP_ID));
        params.put("secret",AppConfig.getProperty(Constants.FLOW_APP_SECRET));
        params.put("grantType","client_credentials");
        String responseBody = RestTemplateUtils.getForEntity(getTokenUrl,params);
        if(StringUtils.isNotBlank(responseBody)){
            Map<String,Object> retMap = JSON.parseObject(responseBody);
            if(retMap.containsKey("code") && "0".equals(retMap.get("code").toString())){
                String data = retMap.get("data").toString();
                Map<String,Object> dataMap = JSON.parseObject(data);
                if(dataMap.containsKey("token") && dataMap.containsKey("expiresIn")){
                    String token = dataMap.get("token").toString();
                    Long expireIn = Long.parseLong(dataMap.get("expiresIn").toString());
                    Date nowTime = new Date();
                    logger.info("时间开始：" + expireIn);
                    logger.info("时间结束：" + nowTime.getTime());
                    long expire = (expireIn - nowTime.getTime() - 3600 * 1000) / 1000;
                    logger.info("时间差：" + expire);
                    redisTemplate.opsForValue().setIfAbsent(redisKey,token,expire, TimeUnit.SECONDS);
                    resultMap.put("token",token);
                    return ResultMapHelper.success(resultMap,ResultMsg.MSG_GET_SUCCESS);
                }
            }
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100, ResultMsg.MSG_GET_FAIL);
    }

    @Override
    public Map<String, Object> save(ParamsMap paramsMap) {
        //未签署
        final int STATUS_0 = 0;
        //已签署
        final int STATUS_1 = 1;
        //已完成
        final int STATUS_2 = 2;
        String flowId = paramsMap.getString("flowId");
        Integer flowStatus = paramsMap.getInteger("flowStatus");
        Integer businessId = paramsMap.getInteger("businessId");
        String accountId = paramsMap.getString("accountId");
        BmsBusinessFlow bmsBusinessFlow = bmsBusinessFlowDao.findByFlowIdAndIsDelete(flowId,Constants.COMMON_FLAG_FALSE_INT);
        if(bmsBusinessFlow == null) {
            List<BmsBusinessFlow> bmsBusinessFlows = bmsBusinessFlowDao.findByBusinessId(businessId);
            if(bmsBusinessFlows != null && bmsBusinessFlows.size() > 0){
                bmsBusinessFlow = bmsBusinessFlows.get(0);
            }else {
                bmsBusinessFlow = new BmsBusinessFlow();
            }
            bmsBusinessFlow.setIsDelete(Constants.COMMON_FLAG_FALSE_INT);
            bmsBusinessFlow.setBusinessId(businessId);
            bmsBusinessFlow.setFlowStatus(STATUS_0);
        }
        bmsBusinessFlow.setFlowId(flowId);
        if(StringUtils.isNotBlank(accountId)) {
            bmsBusinessFlow.setAccountId(accountId);
        }
        if(bmsBusinessFlow.getFlowStatus() == STATUS_0) {
            bmsBusinessFlow.setFlowStatus(flowStatus);
        }
        bmsBusinessFlowDao.save(bmsBusinessFlow);
        if (bmsBusinessFlow.getFlowStatus() == STATUS_1) {
            //获取pdf
            //bmsBusinessFlow.setFlowData(getFlowIDPdfData(flowId));
            BmsCommonService.getApplicationContext().publishEvent(new BusinessFlowEvent("flow",bmsBusinessFlow));
        }
        return ResultMapHelper.success(bmsBusinessFlow,ResultMsg.HAND_SUCCESS);
    }

    private String getFlowIDPdfData(String flowId) {
        final String getPdfDataUrl = "https://openapi.esign.cn/v1/signflows/%s/documents";
        String url = String.format(getPdfDataUrl,flowId);
        try {
            String responseBody = RestTemplateUtils.getForEntity(url);
            Map<String,Object> retMap = JSON.parseObject(responseBody);
            if(retMap.containsKey("code") && "0".equals(retMap.get("code").toString())){
                String data = retMap.get("data").toString();
                return data;
            }
        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
        return null;
    }

    @Override
    public BmsBusinessFlow getBusinessFlowData(Integer businessId) {
        Pageable pageable = BmsCommonService.getPageable(1,1, Sort.Direction.DESC,"newTime");
        List<BmsBusinessFlow> bmsBusinessFlow = bmsBusinessFlowDao.findByBusinessId(businessId,pageable);
        if(bmsBusinessFlow != null && bmsBusinessFlow.size() > 0){
            return bmsBusinessFlow.get(0);
        }
        return null;
    }

    @Override
    public Map<String, Object> getLastPdf(ParamsMap paramsMap) {
        Map<String, Object> tokenMap = this.getToken(paramsMap);
        String token = null;
        if(tokenMap.containsKey("status") && ResultCode.CODE_NORMAL.equals(tokenMap.get("status").toString())){
            Map<String,Object> tokenData = (Map<String, Object>) tokenMap.get("data");
            token = tokenData.get("token").toString();
        }
        if(StringUtils.isNotBlank(token)) {
            String flowId = paramsMap.getString("flowId");

            BmsBusinessFlow bmsBusinessFlow = bmsBusinessFlowDao.findByFlowIdAndIsDelete(flowId,Constants.COMMON_FLAG_FALSE_INT);
            if(bmsBusinessFlow != null){
                //下载pdf
                String trueUrl = String.format(DOWN_URL, bmsBusinessFlow.getFlowId());
                Map<String, Object> paramsMaps = new HashMap<>();
                paramsMaps.put("X-Tsign-Open-App-Id", AppConfig.getProperty(Constants.FLOW_APP_ID));
                paramsMaps.put("X-Tsign-Open-Token", token);
                String reponseBody = RestTemplateUtils.getForEntity(trueUrl,new HashMap<>(),paramsMaps);
                if (StringUtils.isNotBlank(reponseBody)) {
                    Map<String, Object> reponseBodyMap = JSON.parseObject(reponseBody);
                    if(reponseBodyMap.containsKey("code") && Integer.parseInt(reponseBodyMap.get("code").toString()) == 0){
                        //判断成功
                        FlowDocument flowDocument = JSON.parseObject(reponseBodyMap.get("data").toString(),FlowDocument.class);
                        return ResultMapHelper.success(flowDocument,ResultMsg.MSG_GET_SUCCESS);
                    }
                }
            }
        }
        return ResultMapHelper.result(ResultCode.CODE_ERROR_100,ResultMsg.MSG_GET_FAIL);
    }
}
